
// 注意事项：
// ******收费接口，所以不应该频繁重启。
// ******重启后，需要给一定的时间，让模块获取到足够的代理节点。
//
// 使用未例：
// var proxyReq = require('./util/proxyRequest.js');
// var proxyReqInstance = proxyReq.createInstance('140311f0fb0c435f8e982f5b8e10513a', 20);
//
// var options = {
//     url : urlGet,
//     method : 'GET',
//     headers:{}
// };
// proxyReqInstance.proxyRequest(options, function (error, response, body) {
// });

var proxyReq = {};
var request = require('request');

var CHECK_IP_COUNT_INTERVAL = 10000;
var URL_FOR_TEST_PROXY = 'http://ip.htaoke.com/';

function requestWithProxy(ip, opt, cb) {
    var opt1 = {};
    for(var k in opt) opt1[k] = opt[k];
    if(ip){
        opt1.proxy = 'http://' + ip.ip + ':' + ip.port;
        request(opt1, cb);
    }
    else{
        cb('no avail ip proxy!');
    }
}
function onGetIp(err, instance, ips) {
    if(err){
        console.log(err);
        return;
    }
    ips.forEach(function (ip) {
        testAndAddIp(instance, ip);
    })
}
function getSomeIp(instance) {
    var urlGetIp = 'http://ip.htaoke.com/get_ip5/';
    // if(instance.ipSize <= 5) urlGetIp = 'http://ip.htaoke.com/get_ip5/';
    // else if(instance.ipSize <= 10) urlGetIp = 'http://ip.htaoke.com/get_ip10/';
    // else if(instance.ipSize <= 20) urlGetIp = 'http://ip.htaoke.com/get_ip20/';
    // else urlGetIp = 'http://ip.htaoke.com/get_ip/';
    // var urlGetIp = 'http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=' + instance.appId + '&count=' + getCount + '&expiryDate=0&format=1';
    var options = {
        url : urlGetIp,
        headers:{}
    };
    request(options, function (error, response, body) {

        if (error || response.statusCode != 200 || !body) {
            onGetIp('取IP代理失败！', response, body);
            return;
        }
        try {
            if (!body || body.length < 2 || '{['.indexOf(body.substr(0, 1)) < 0 ) {
                onGetIp('取代理IP失败！', response, body);
                return;
            }
            var rsp = JSON.parse(body);

            if(!rsp || !rsp.msg){
                onGetIp('取代理IP失败！', response, body);
                return;
            }
            if(!rsp.msg || rsp.msg.length <= 0){
                onGetIp('取代理IP失败！', response, body);
                return;
            }
            onGetIp(null, instance, rsp.msg);
        }
        catch (e) {
            onGetIp('取代理IP失败！', response, body);
        }
    });
}
function testAndAddIp(instance, ip) {
    var urlGetIp = URL_FOR_TEST_PROXY;
    var options = {
        url : urlGetIp,
        timeout:5000,
        headers:{}
    };
    requestWithProxy(ip, options, function (error, response, body) {
        if (error || response.statusCode != 200 || !body || body.indexOf(ip.ip) < 0) {
            console.log('测试代理IP失败！' + JSON.stringify(ip));
            // console.log(error);
            return;
        }
        instance.proxys.push(ip);
        console.log('IP added: ' + JSON.stringify(ip));
    })
}
function removeIp(instance, ip) {
    for(var i = 0; i < instance.proxys.length; ++i){
        if(instance.proxys[i].ip == ip.ip && instance.proxys[i].port == ip.port){
            instance.proxys.splice(i, 1);
            return;
        }
    }
}
proxyReq.createInstance = function (appId, ipSize) {
    var instance = {};
    instance.appId = appId;
    instance.ipSize = ipSize;
    instance.proxys = [];
    instance.curIpIndex = 0;
    getSomeIp(instance);
    setInterval(function () {
        if(instance.proxys.length < instance.ipSize){
            getSomeIp(instance);
        }
    }, CHECK_IP_COUNT_INTERVAL);
    instance.proxyRequestWithRetry = function (options, retryTimes, cb) {
        ++instance.curIpIndex;
        if(instance.curIpIndex >= instance.proxys.length){
            instance.curIpIndex = 0;
        }
        var ip = instance.proxys[instance.curIpIndex];
        requestWithProxy(ip, options, function (err, response, body) {
            if(ip && err && (err.code == 'ECONNREFUSED' || err.code == 'ETIMEDOUT' || err.code == 'ECONNRESET')){
                if(!ip.hasOwnProperty('failCount')) ip.failCount = 1;
                else ++ip.failCount;
                removeIp(instance, ip);

                // 先移出队列，如果失败次数小于3次，则再次测试是否可用。
                if(ip.failCount < 3) testAndAddIp(instance, ip);

                --retryTimes;
                if(retryTimes > 0){
                    setTimeout(function () {
                        instance.proxyRequestWithRetry(options, retryTimes, cb);
                    }, 10);
                    return;
                }
            }
            else if(ip){
                delete ip.failCount;
            }
            cb(err, response, body);
        })
    };
    instance.proxyRequest = function (options, cb) {
        instance.proxyRequestWithRetry(options, 3, cb);
    };
    return instance;
};

module.exports = proxyReq;